<?php

namespace app\http\controller\chat;

use Exception;
use Laf\Cookie;
use Laf\Session;
use mon\util\Tool;
use app\libs\View;
use mon\util\File;
use FApi\Response;
use Laf\Controller;
use mon\env\Config;
use mon\captcha\Captcha;
use mon\util\UploadFile;
use GatewayClient\Gateway;
use app\model\SettingModel;
use app\model\ChatAppModel;
use app\model\ChatStayModel;
use app\model\ChatMessageModel;
use app\model\ChatMessageRelationModel;
use mon\util\exception\UploadException;

/**
 * 即时通信客户端接口
 */
class ClientController extends Controller
{
    /**
     * 主页
     *
     * @param string $app app名称
     * @return string
     */
    public function index($app)
    {
        // post请求，记录留言信息
        if ($this->request->isPost()) {
            return $this->stay($app);
        }
        $info = ChatAppModel::instance()->getInfo(['name' => $app, 'status' => 1]);
        if (!$info) {
            return $this->url->abort(404);
        }
        $group = 'kf_' . $app;
        try {
            // 链接workerman，获取当前在线的客服数，判断是否存在在线客服
            Gateway::$registerAddress = Config::instance()->get('socket.gateway.registerAddress');
            $waiterCount = Gateway::getClientIdCountByGroup($group);
        } catch (Exception $e) {
            // 链接workerman异常，不启用在线客服，打开留言页面
            $waiterCount = 0;
        }
        $useKF = ($waiterCount > 0);
        // 存在在线客服则进入在线通信页面，不存在则进入留言页面
        $view = $useKF ? 'chat/client/index' : 'chat/client/stay';

        $template = new View();
        $config = SettingModel::instance()->getConfig('chat');
        $tools = explode(',', $info['tools']);
        $jsConfig = [
            'server'    => $config["server_address"],
            'app'       => $info['name'],
            'cmd'       => 'visitor',
            'title'     => $info['title'],
            'logo'      => $info['logo'],
            'home'      => $info['home'],
            'tools'     => $tools,
            'user'      => $config['chat_username'],
            'wellcome'  => $info['wellcome'],
            'emojiSetting' => ['path' => '/static/libs/monEmoji/img/'],
        ];
        if (in_array('file', $tools)) {
            $jsConfig['uploadLink'] = $this->url->build('/chat/upload', [], true);
        }

        if ($useKF) {
            // 种下websocket-ticket
            $socketSafeConfig = Config::instance()->get('socket.safe');
            Cookie::instance()->set($socketSafeConfig['name'], $app);
            Tool::instance()->createTicket($app, $socketSafeConfig['salt'], $socketSafeConfig['expire'], $socketSafeConfig['token'], $socketSafeConfig['time']);
        }

        $template->assign('config', $jsConfig);
        return $template->fetch($view);
    }

    /**
     * 记录留言
     *
     * @param string $app
     * @return void
     */
    public function stay($app)
    {
        $data = $this->request->post();
        // 校验验证码
        if (!isset($data['captcha']) || empty($data['captcha'])) {
            return $this->error('请输入验证码');
        }
        $id = Config::instance()->get('chat.stay_captcha_id');
        $config = Config::instance()->get('captcha');
        $captcha = new Captcha($config);
        if (!$captcha->check($data['captcha'], $id)) {
            return $this->error('验证码错误');
        }
        $data['app_name'] = $app;
        $save = ChatStayModel::instance()->record($data);
        if (!$save) {
            return $this->error(ChatStayModel::instance()->getError());
        }

        return $this->success('留言成功');
    }

    /**
     * 获取JS
     *
     * @param string $app app名称
     * @return Response
     */
    public function js($app)
    {
        $info = ChatAppModel::instance()->getInfo(['name' => $app, 'status' => 1]);
        if (!$info) {
            return $this->url->abort(404);;
        }

        $showList = [];
        foreach (explode(',', $info['display']) as $item) {
            if (in_array($item, ['top'])) {
                $showList[$item] = true;
            } else if (isset($info[$item]) && !empty($info[$item])) {
                $showList[$item] = $info[$item];
            }
        }

        $template = new View();
        $template->assign('info', $info);
        $template->assign('container', $this->container);
        $template->assign('showList', $showList);
        return Response::create($template->fetch('chat/client/kefu_js'), 'js');
    }

    /**
     * 获取验证码图片
     *
     * @return Response
     */
    public function captcha()
    {
        $id = Config::instance()->get('chat.stay_captcha_id');
        $config = Config::instance()->get('captcha');
        $captcha = new Captcha($config);
        $data = $captcha->create($id, false);
        return Response::create($data)->header(['Content-Type' => 'image/png']);
    }

    /**
     * 文件上传
     *
     * @return string
     */
    public function upload(UploadFile $sdk)
    {
        // 访问权限控制
        $chat_app = Cookie::instance()->get('chat_app');
        if (!Tool::instance()->checkTicket($chat_app, null, null, Config::instance()->get('socket.safe.salt'), false)) {
            return $this->url->abort(401);
        }
        // 判断有效的应用
        $appInfo = ChatAppModel::instance()->getInfo(['name' => $chat_app, 'status' => 1]);
        if (!$appInfo) {
            return $this->url->abort(402);;
        }

        // 判断是否为客服人员上传
        $userInfo = Session::instance()->get(Config::instance()->get('chat.userInfo'));
        if (!$userInfo) {
            // 非已登录的客服人员，验证app是否开发上传的功能
            $auth = explode(',', $appInfo['tools']);
            if (!in_array('file', $auth)) {
                return $this->url->abort(403);
            }
        }

        $config = SettingModel::instance()->getConfig('chat');
        if (!$config) {
            return $this->url->abort(501);
        }
        $rootPath = ROOT_PATH . '/public';
        $savePath = '/upload/chat';
        $date = date('Ym');
        $saveDir = $rootPath . DIRECTORY_SEPARATOR . $savePath . DIRECTORY_SEPARATOR . $date . DIRECTORY_SEPARATOR;
        if (!is_dir($saveDir)) {
            $createDir = File::instance()->createDir($saveDir);
            if (!$createDir) {
                return $this->error('创建存储目录失败');
            }
        }
        $sdk->rootPath = $saveDir;
        $sdk->maxSize = $config['chat_upload_maxsize'];
        $sdk->exts = explode(',', $config['chat_upload_type']);
        try {
            $upload = $sdk->upload()->save()->getFile();
            $path = $this->url->build($savePath . '/' . $date . '/' . $upload['saveName'], [], true);
            return $this->success('ok', ['url' => $path]);
        } catch (UploadException $e) {
            return $this->error($e->getMessage());
        }
    }

    /**
     * 拉去聊天记录
     *
     * @param string $waiter_id 客服ID
     * @param string $app       应用APP名称
     * @param string $visitid   访客ID
     * @param ChatMessageRelationModel $messageRelation  聊天关系模型
     * @param ChatMessageModel $message  聊天记录模型
     * @return string
     */
    public function pull($waiter_id, $app, $visitid, ChatMessageRelationModel $messageRelation, ChatMessageModel $message)
    {
        // 验证参数
        $uid = code2id($waiter_id);
        if (!$uid) {
            return $this->error('waiter_id params invalid');
        }
        if (empty($app)) {
            return $this->error('app params invalid');
        }
        if (empty($visitid)) {
            return $this->error('visitid params invalid');
        }
        // 种下cookie的ticket
        Cookie::instance()->set('chat_app', $app, ['expire' => 3600]);
        Tool::instance()->createTicket($app, Config::instance()->get('socket.safe.salt'));
        // 获取聊天关系表ID
        $relation = $messageRelation->where('app_name', $app)->where('waiter_id', $uid)->where('visitid', $visitid)->find();
        if (!$relation) {
            // 不存在记录，直接返回空列表
            return $this->success('ok', []);
        }
        // 获取聊天记录
        $list = $message->getMessage($relation['id'], ['content', 'ip', 'create_time']);
        return $this->success('ok', $list);
    }
}
